package com.zy.ems.common.base;

import java.io.Serializable;
import java.util.List;

import javax.annotation.Resource;

import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.dao.DataAccessException;

import com.zy.ems.common.page.PageQuery;
import com.zy.ems.common.page.PageQueryBuilder;
import com.zy.ems.common.page.PaginationResult;
import com.zy.ems.common.page.Paginator;

/**
 * 持久层公共方法抽象类。
 * 
 * @author Luffy
 *
 * @param <E>
 * @param <PK>
 */
public abstract class BaseDao<E extends BaseEntity, PK extends Serializable> extends SqlSessionDaoSupport {

	/**
	 * 获取对应实体的映射器。
	 * 
	 * @return
	 */
	protected abstract <T extends BaseMapper<E, PK>> T getMapper();

	/**
	 * 获取Mapper命名空间。
	 * 
	 * @return
	 */
	protected abstract String getNamespace();

	/**
	 * 注入sqlSessionFactory。
	 * 
	 * @param sqlSessionFactory
	 */
	@Resource(name = "sqlSessionFactory")
	public void setSuperSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
		super.setSqlSessionFactory(sqlSessionFactory);
	}

	/**
	 * 根据主键查询数据。
	 * 
	 * @param id
	 * @return
	 * @throws DataAccessException
	 */
	public E getById(PK id) throws DataAccessException {
		return this.getMapper().getById(id);
	}

	/**
	 * 根据主键删除数据。
	 * 
	 * @param id
	 * @throws DataAccessException
	 */
	public void deleteById(PK id) throws DataAccessException {
		this.getMapper().deleteById(id);
	}

	/**
	 * 插入数据。
	 * 
	 * @param entity
	 * @throws DataAccessException
	 */
	public void save(E entity) throws DataAccessException {
		this.getMapper().insertEntity(entity);
	}

	/**
	 * 更新数据。
	 * 
	 * @param entity
	 * @throws DataAccessException
	 */
	public void update(E entity) throws DataAccessException {
		this.getMapper().updateEntity(entity);
	}

	/**
	 * 唯一性检查。
	 * 
	 * @param entity
	 * @param uniquePropertyNames
	 * @return
	 * @throws DataAccessException
	 */
	public boolean isUnique(E entity, String uniquePropertyNames) throws DataAccessException {
		return this.getMapper().isUnique(entity, uniquePropertyNames);
	}

	/**
	 * 查询所有数据。
	 * 
	 * @return
	 * @throws DataAccessException
	 */
	public List<E> findAll() throws DataAccessException {
		return this.getMapper().findAll();
	}

	/**
	 * 获取分页数据，包含分页信息。<br>
	 * 此方法按默认的查询语句标识符进行分页查询。
	 * 
	 * @param parameter
	 * @param start
	 *            当前页偏移量
	 * @param pageSize
	 *            分页大小
	 * @return
	 */
	public final <V> PaginationResult<V> findPageList(Object parameter, int start, int pageSize) {
		PageQuery pageQuery = PageQueryBuilder.instance().offset(start).pageSize(pageSize).build();
		return this.findPageList(PageStmtUID.DEFAULT, parameter, pageQuery);
	}

	/**
	 * 获取分页数据，包含分页信息。<br>
	 * 此方法按默认的查询语句标识符进行分页查询。
	 * 
	 * @param parameter
	 * @param pageQuery
	 *            分页查询对象
	 * @return
	 */
	public final <V> PaginationResult<V> findPageList(Object parameter, PageQuery pageQuery) {
		return this.findPageList(PageStmtUID.DEFAULT, parameter, pageQuery);
	}

	/**
	 * 获取分页数据，包含分页信息。
	 * 
	 * @param pageStmtUID
	 * @param parameter
	 * @param pageQuery
	 *            分页查询对象
	 * @return
	 */
	public final <V> PaginationResult<V> findPageList(PageStmtUID pageStmtUID, Object parameter, PageQuery pageQuery) {
		// 查询总数量
		Number totalCount = (Number) this.getSqlSession().selectOne(getFullStatement(pageStmtUID.getCountStmt()),
				parameter);
		// 总数量为空时只返回分页信息
		if (totalCount == null || totalCount.intValue() <= 0) {
			return new PaginationResult<V>(pageQuery.getPage(), pageQuery.getPageSize(), 0);
		}
		// 构造分页信息
		Paginator paginator = new Paginator(pageQuery.getPage(), pageQuery.getPageSize(), totalCount.intValue());
		// 查询请求的当前页数据
		List<V> list = this.getSqlSession().selectList(getFullStatement(pageStmtUID.getPageStmt()), parameter,
				new RowBounds(paginator.getOffset(), paginator.getPageSize()));
		// 返回分页数据列表
		return new PaginationResult<V>(list, paginator);
	}

	private String getFullStatement(String statementId) {
		return getNamespace().concat(".").concat(statementId);
	}

}
